package com.demo.task.manager

import android.util.Log
import com.demo.task.BuildConfig
import com.demo.task.config.Config
import com.demo.task.socket.RemoteInterface
import com.demo.task.socket.SocketIO
import com.demo.task.utils.LocationUtils
import com.google.gson.Gson
import com.kongqw.serialportlibrary.SerialPortManager
import com.kongqw.serialportlibrary.listener.OnSerialPortDataListener
import com.zed.service.APIHelper
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.runBlocking
import tp.xmaihh.serialport.SerialHelper
import tp.xmaihh.serialport.bean.ComBean
import java.io.File

class GpsManager(
    private val socketIO: RemoteInterface
) {
    companion object {
        private const val TAG = "GpsManager"
    }

    private val apiHelper by lazy { APIHelper.getInstance() }
    private val locationUtils by lazy { LocationUtils() }

    private val _visOverlay = MutableSharedFlow<Boolean>()
    val visOverlay: SharedFlow<Boolean> get() = _visOverlay

    private val dataList = mutableListOf<Double>()

    private val serialUsb1: SerialPortManager by lazy {
        SerialPortManager().apply {
            setOnSerialPortDataListener(object : OnSerialPortDataListener {
                override fun onDataReceived(bytes: ByteArray) {
                    process(bytes)
                }

                override fun onDataSent(bytes: ByteArray) {
                    Log.i(TAG, "onDataSent: serialUsb1")
                }
            })
        }
    }


    private val serialUsb2: SerialHelper by lazy {
        val path = when (BuildConfig.FLAVOR) {
            "A" -> "/dev/ttyUSB0"
            else -> "/dev/ttyUSB3"
        }
        object : SerialHelper(path, 115200) {
            override fun onDataReceived(p0: ComBean?) {
                Log.i(TAG, "onDataReceived: $p0")
            }
        }
    }
    private val serialUsb3: SerialHelper by lazy {
        val path = when (BuildConfig.FLAVOR) {
            "A" -> "/dev/ttyUSB1"
            else -> "/dev/ttyUSB4"
        }
        object : SerialHelper(path, 115200) {
            override fun onDataReceived(p0: ComBean?) {
                Log.i(TAG, "onDataReceived: $p0")
            }
        }
    }

    fun activate() {
        if (isTtyUSB0Exists()) {
            val path = when (BuildConfig.FLAVOR) {
                "A" -> "/dev/ttyUSB6"
                else -> "/dev/ttyUSB1"
            }

            // 如果 ttyUSB0 存在并且可访问
            Log.d("SerialPort", "ttyUSB0 exists and can be accessed")
            runCatching {
                serialUsb2.open()
                Config.isOpenGps = true
            }.onFailure { Log.e(TAG, "serialUsb2.open(): ", it) }
            serialUsb2.sendTxt("AT+QGPS=1\r\n")
            serialUsb1.openSerialPort(File(path), 115200)
        } else {
            val path = when (BuildConfig.FLAVOR) {
                "A" -> "/dev/ttyUSB7"
                else -> "/dev/ttyUSB2"
            }

            // 如果 ttyUSB0 不存在或无法访问
            Log.e("SerialPort", "ttyUSB0 not found or cannot be accessed")
            runCatching {
                serialUsb3.open()
                Config.isOpenGps = true
            }.onFailure { Log.e(TAG, "serialUsb3.open(): ", it) }
            serialUsb3.sendTxt("AT+QGPS=1\r\n")
            serialUsb1.openSerialPort(File(path), 115200)
        }

    }

    fun isTtyUSB0Exists(): Boolean {
        val ttyUSB0 = File("/dev/ttyUSB0")
        return ttyUSB0.exists() && ttyUSB0.canRead() && ttyUSB0.canWrite()
    }

    fun getSerialPortList(): List<String> {
        val serialPorts = mutableListOf<String>()

        // 获取设备上所有文件列表
        val devDir = File("/dev")
        if (devDir.exists() && devDir.isDirectory) {
            // 列出以 tty 开头的设备文件，这通常是串口设备
            devDir.listFiles()?.forEach { file ->
                if (file.name.startsWith("tty")) {
                    serialPorts.add(file.absolutePath)
                }
            }
        }

        return serialPorts
    }

    private fun process(bytes: ByteArray) {
        val receivedData = String(bytes)

        // 按换行符分割字符串，获取每一行
        val lines = receivedData.split("\\$".toRegex()).toTypedArray()
        // 遍历每一行，检查是否以 $GPGGA 或 $GPVTG 开头
        var longitudeStr: String? = null
        var latitudeStr: String? = null
        var gpsSpeed: Double? = null

        val protocol = when (BuildConfig.FLAVOR) {
            "A" -> Pair("GNRMC", "GNVTG")
            else -> Pair("GPRMC", "GPVTG")
        }

        lines.forEach { line ->
            when {
                line.startsWith(
                    protocol.first +
                            ""
                ) -> {
                    // 处理以 $GPGGA 开头的行
                    //Log.i("GPGGAGPGGA", "GPGGA 数据: $line")
                    val parts = line.split(",").toTypedArray()

                    // 检查 parts 数组的长度
                    if (parts.size > 5) { // 确保有足够的部分
                        longitudeStr = parts[5] // 经度
                        latitudeStr = parts[3] // 纬度
                        Log.d(TAG, "经度为：$longitudeStr")
                        Log.d(TAG, "纬度为：$latitudeStr")
                        setTimeFromGPRMC(line)
                    }
                }

                line.startsWith(protocol.second) -> {
                    // 处理以 $GPVTG 开头的行
                    val parts2 = line.split(",").toTypedArray()

                    if (parts2.size > 7) {
                        val gpsSpeedString = parts2[7] // 速度
                        gpsSpeed = gpsSpeedString.toDoubleOrNull()
                            ?: 0.00 // 将速度转换为 Double，若转换失败则默认为 0.0
                        Log.d(TAG, "速度为：$gpsSpeed")

                        dataList.add(gpsSpeed!!)
                        val average = dataList.average()
                        Log.d(TAG, "当前 ${dataList.size}个元素: $dataList, 平均值: $average")
                        if (dataList.size >= 5) {
                            dataList.clear() // 清空列表以便存储下一批数据
                        }
                        // 根据速度值设置黑色遮罩的可见性
                        runBlocking {
                            _visOverlay.emit(
                                ((average < 3.6))
                            )
                        }
                    }
                }

                else -> {
                    // 忽略其他行或进行其他处理
                }
            }
        }

        upload(longitudeStr, latitudeStr, gpsSpeed)
    }

    private fun upload(
        longitudeStr: String?,
        latitudeStr: String?,
        gpsSpeed: Double?
    ) {
        val params = mapOf(
            "first" to longitudeStr,
            "second" to latitudeStr,
            "third" to gpsSpeed
        )
        val message = mapOf(
            "type" to "gps",
            "message" to params
        )
        if (!longitudeStr.isNullOrEmpty() && !latitudeStr.isNullOrEmpty()) {
            val distance = locationUtils.getDistance(longitudeStr, latitudeStr)
            if (distance > 15) {
                socketIO.send(Gson().toJson(message))
            }
        }
    }

    private fun setTimeFromGPRMC(gprmc: String) {
        // 提取时间字段（GPRMC格式中的第二个字段是时间，格式为 "hhmmss.sss"）
        val fields = gprmc.split(",")
        if (fields.size >= 10) {
            val timeString = fields[1]
            val dateString = fields[9]
            Log.d(TAG, "gpstimeString: ${dateString}")
            // 判断时间部分是否有效
            if (timeString.length >= 6 && timeString.toDoubleOrNull() != null && timeString.toDouble() > 0 && dateString.length == 6) {
                try {
                    // 时间字符串解析为小时、分钟、秒
                    var hours = timeString.substring(0, 2).toInt()
                    var minutes = timeString.substring(2, 4).toInt()
                    var seconds = timeString.substring(4, 6).toInt()

                    // 转换为 GMT+9 时间
                    hours += 9
                    val extraDays = hours / 24
                    hours %= 24

                    // 解析日期
                    var year = ("20" + dateString.substring(4, 6)).toInt()
                    var month = dateString.substring(2, 4).toInt()
                    var day = dateString.substring(0, 2).toInt()

                    // 处理日期变更
                    for (i in 0 until extraDays) {
                        day++
                        val maxDays = getMaxDaysInMonth(year, month)
                        if (day > maxDays) {
                            day = 1
                            month++
                            if (month > 12) {
                                month = 1
                                year++
                            }
                        }
                    }

                    Log.e(TAG, "setSysTime: in${year}")
                    // 调用setSysTime设置系统时间
                    runCatching {
                        apiHelper.setSysTime(year, month, day, hours, minutes, seconds)
                    }.onFailure {
                        Log.e(TAG, "setSysTime: ", it)
                    }.onSuccess {
                        Log.i(TAG, "setSysTime: onSuccess")
                    }
                } catch (e: Exception) {
                    println("Error parsing time or date: ${e.message}")
                }
            } else {
                println("Invalid time in GPRMC string, skipping system time update.")
            }
        } else {
            println("Invalid GPRMC string format.")
        }
    }

    private fun getMaxDaysInMonth(year: Int, month: Int): Int {
        return when (month) {
            1, 3, 5, 7, 8, 10, 12 -> 31
            4, 6, 9, 11 -> 30
            2 -> if (isLeapYear(year)) 29 else 28
            else -> throw IllegalArgumentException("Invalid month: $month")
        }
    }

    private fun isLeapYear(year: Int): Boolean {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
    }
}